package com.tiny_wind.resource_manager.controller;

import com.auth0.jwt.interfaces.Claim;
import com.tiny_wind.resource_manager.entity.TokenEntity;
import com.tiny_wind.resource_manager.entity.UserEntity;
import com.tiny_wind.resource_manager.model.TwResultModel;
import com.tiny_wind.resource_manager.service.impl.UserServiceImpl;
import com.tiny_wind.resource_manager.utility.GaJJwtManager;
import com.tiny_wind.resource_manager.utility.GaLogManager;
import com.tiny_wind.resource_manager.utility.GaTimeManager;
import com.tiny_wind.resource_manager.utility.ResponseCodeManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import java.util.Map;

@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController extends BaseController {
    public static String TAG = "UserController";
    private Logger logger = LogManager.getLogger(this.getClass());

    @Autowired
    private UserServiceImpl mService;


    @RequestMapping(value = "/register", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<UserEntity> register(@RequestBody UserEntity user) {
        logger.info("UserController/login,account:{},password:{}",user.account,user.password);
        try {
            UserEntity entity = mService.searchByAccount(user.account);
            //用户已存在. -1;
            if(entity != null) {
                TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(ResponseCodeManager.CODE_USER_ALREADY_REGISTERED);
                return result;
            }
            mService.register(user);
            TwResultModel<UserEntity> result = new TwResultModel<UserEntity>();
            return result;
        }
        catch (Exception e) {
            logger.debug("TodoController/search exception,%s",e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    @RequestMapping(value = "/login2", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<UserEntity> login(@RequestBody UserEntity filter) {
        logger.info("UserController/login,account:{},password:{}",filter.account,filter.password);
        try {
            UserEntity entity = mService.login(filter.account, filter.password);
            //用户不存在. -1;
            if(entity == null) {
                TwResultModel<UserEntity> result = new TwResultModel<>(-1, "No such account");
                return result;
            }
            if(entity.password.equals(filter.password)) {
                String token = storeToken(entity.account, entity.id);
                TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(entity);
                entity.token = token;
                Cookie cookie = new Cookie("token",token);
                cookie.setPath("/");
                cookie.setMaxAge(7200);
                response.addCookie(cookie);
                return result;
            }
            else {
                TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(-2, "Invalid password");
                return result;
            }
        }
        catch (Exception e) {
            logger.debug("TodoController/search exception,%s",e.getMessage());
            e.printStackTrace();
            return null;
        }

    }


    /**
     * 通过Token登录,换取新Token.
     * @param filter
     * @return
     */
    @RequestMapping(value = "/Login/Token", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<UserEntity> loginWithToken(@RequestBody UserEntity filter) {
        logger.info("UserController/loginWithToken,token is:%s",filter.token);
        try {

            Map<String, Claim> map = null;
            try {
                map = GaJJwtManager.verifyToken(filter.token);
            } catch (Exception e) {
                //过期
                logger.warn("token expired!");
                String url = String.format("%s/User/NoToken?code=%d",request.getContextPath(), ResponseCodeManager.errorCode_expiredToken);
                return new TwResultModel<UserEntity>(-1,"Token is expired");
            }
            Claim claim = map.get("userId");
            Integer userId = claim.asInt();

            UserEntity user = mService.searchByUserId(userId);

            //重新生成token并保存.
            String token = storeToken(user.account, user.id);
            TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(user);
            user.token = token;
            Cookie cookie = new Cookie("token",token);
            cookie.setPath("/");
            cookie.setMaxAge(7200);
            response.addCookie(cookie);
            return result;
        }
        catch (Exception e) {
            logger.debug("TodoController/search exception,%s", e.getMessage());
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 1,生成一个token,插入到表中.
     * 2,返回该token.
     * @param userAccount
     * @param userId
     * @return
     */
    public String storeToken(String userAccount,Integer userId) {
        String token = GaJJwtManager.generatorToken(userAccount, userId);
        String info = String .format("UserController/storeToken,token is: %s",token);
        logger.info(info);
        String expireTime = GaTimeManager.sharedInstance.stdTimeStringAfterNow(GaJJwtManager.ms_expireTime);
        TokenEntity entity = new TokenEntity(token,userId,expireTime);
        try {
            mService.insertToken(entity);
        }
        catch (Exception e) {
            //重复插入.
            info = e.getLocalizedMessage();
            logger.warn(info);
        }
        return token;
    }


    @RequestMapping(value = "/NoToken", method = RequestMethod.GET)
    @ResponseBody
    public TwResultModel<Object> noToken(int code) {
        GaLogManager.v_c(TAG,"Path","noToken");
        return new TwResultModel<Object>( ResponseCodeManager.errorCode_noToken,ResponseCodeManager.getCodeMessage(ResponseCodeManager.errorCode_noToken));
    }
    @RequestMapping(value = "/NoToken", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<Object> noToken_post() {
        GaLogManager.v_c(TAG,"Path","noToken_post");
        return new TwResultModel<Object>( ResponseCodeManager.errorCode_noToken,ResponseCodeManager.getCodeMessage(ResponseCodeManager.errorCode_noToken));
    }
}